package engine.BIEngine0_1;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

import beans.*;
import dao.JobDao;
import dao.TaskDao;
import net.QueryThread;
import net.sf.json.JSONObject;
import portal.common.MyStringUtils;
import utils.Log4jInit;

/**
 *
 * @author zhuyaokun
 *
 */
public class TaskThread extends Thread implements Serializable {

    private static final long serialVersionUID = 3105558278814128515L;
    public RunningTaskBean runningTaskBean;
    public String applyNode = null;

	/**
	 * constructor
	 */
	public TaskThread(RunningTaskBean runningTaskBean) {
		this.runningTaskBean = runningTaskBean;
	}
	
	public TaskThread(RunningTaskBean runningTaskBean,String applyNode) {
		this.runningTaskBean = runningTaskBean;
		this.applyNode = applyNode;
	}

	public TaskThread(RunnableTask runnableTask) {

	}

	/**
	 * start a task or a nested task
	 */
	public void startTask(){
		Log4jInit.logger.info("runnableObjects style:"+runningTaskBean.runnableObjects.keySet());
		if(runningTaskBean.runnableObjects.containsKey("startAlgorithms")){
			String startAlgorithmHashs = (String) runningTaskBean.runnableObjects.get("startAlgorithms");
			String startModelHashs = (String) runningTaskBean.runnableObjects.get("startModels");
			
			for(String startAlgorithmHash:startAlgorithmHashs .split(",")){
				this.startHash(startAlgorithmHash, 1, true);
				
			}
		}
		if(runningTaskBean.runnableObjects.containsKey("startModels")){
			String startModelHashs = (String) runningTaskBean.runnableObjects.get("startModels");
			
			 int count=0;
			for(String startAlgorithmHash:startModelHashs .split(",")){
				this.startHash(startAlgorithmHash, 0, true);
				
                //线程等待
     /*   count++;
        if(count%10==0){
       	 try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
                }*/
                
			}
		}
	}
	/**
	 * update task state by task or algorithm thread
	 *
	 * @param state
	 */
	public void updateState(String state) {
//		System.out.println("task state:\n\t"+state);
		state = runningTaskBean.sf.format(new Date()) + "	" + state;
		this.runningTaskBean.newestState = this.runningTaskBean.newestState+state+"\n";
		this.runningTaskBean.state.append(state+"\n");
		this.runningTaskBean.historyDao.updateRunningHistoryTaskState(this.runningTaskBean.state.toString(),
				this.runningTaskBean.getTaskHash());
	}
	
	/**
	 * 完成任务后，只state描述简化。
	 * @return
	 */
	public void updateStateFinish(String state,boolean finish) {
//		System.out.println("task state:\n\t"+state);
		state = runningTaskBean.sf.format(new Date()) + "	" + state;
	//	this.runningTaskBean.newestState = this.runningTaskBean.newestState+state+"\n";
		this.runningTaskBean.newestState = state+"\n";
		//this.runningTaskBean.state.append(state+"\n");
		this.runningTaskBean.state=new StringBuilder(state+"\n");
		this.runningTaskBean.historyDao.updateRunningHistoryTaskState(this.runningTaskBean.state.toString(),this.runningTaskBean.getTaskHash());
	}

	public String getNewestState() {
		String result = this.runningTaskBean.newestState;
		this.runningTaskBean.gotNewestState = true;
		this.runningTaskBean.newestState = "";
		return result;
	}

	/**
	 * 暂停一个子任务
	 *
	 * @return
	 */
	public boolean pauseTask() {
//		this.runningTaskBean.isPause = true;
//		String newestAlgorithm = this.runningTaskBean.newestAlgorithm;
//		if(this.runningTaskBean.runningAlgorithms.containsKey(newestAlgorithm)){
//			AlgorithmThread algorithmThread = this.runningTaskBean.runningAlgorithms.get(newestAlgorithm);
//			return algorithmThread.pauseAlgorithm();
//		}else{
//			System.out.println("要暂停的任务的runningAlgorithm里面有东西，size大于0，但是不包含newestAlgorithm，应该是newestAlgorithm出错了");
//			return true;
//		}
		//2018-7-21修改
		boolean result = true;
		this.runningTaskBean.isPause = true;
		Map<String,List<String>> runningJobs = new HashMap<>();
        //将本子任务对应的正在运行的作业全部记录下来
        for(Map.Entry<String,AlgorithmThread> one:this.runningTaskBean.runningAlgorithms.entrySet())
		{
            runningJobs.put(one.getKey(),one.getValue().getRunningJobIds());
        }
        this.runningTaskBean.setRunningJobs(runningJobs);
        //将TaskThread对象序列化到数据库
        result = result&&new TaskDao().serializeTask2DB(this);
        //将本子任务对应的正在运行的对象全部停下来
        for(Map.Entry<String,AlgorithmThread> one:this.runningTaskBean.runningAlgorithms.entrySet())
        {
            result = result&&one.getValue().pauseAlgorithm();
        }
		//到数据库更新任务的状态
		result = result&&this.terminateTask("pause");
		//result为true：一个或多个或所有算法都正确停止了或者完成了
		//result为false：一个或多个或所有算法停止失败了
		return result;
	}
	/**
	 * tomcat关闭，与服务器断开连接
	 *
	 * @return
	 */
	public boolean disconnectTask() {
		Map<String,List<String>> runningJobs = new HashMap<>();
		//将本子任务对应的正在运行的作业全部记录下来
		for(Map.Entry<String,AlgorithmThread> one:this.runningTaskBean.runningAlgorithms.entrySet())
		{
			runningJobs.put(one.getKey(),one.getValue().getRunningJobIds());
		}
		this.runningTaskBean.setRunningJobs(runningJobs);
		//将TaskThread对象序列化到数据库
		return new TaskDao().serializeTask2DB(this);
	}
	/**
	 * tomcat启动，与服务器恢复连接
	 *
	 * @return
	 */
	public boolean connectTask(String token) {
		List<Object> jobs = new JobDao().getRunningJobState(this.runningTaskBean.getTaskHash());
		boolean isSuccess = true;
		for(Object object:jobs){
			JSONObject job = (JSONObject)object;
			HttpResultList result = null;
			try {
				//获取作业详情
				result = AlgorithmOperator.getJobFullState(job.getString("jobId"), token);
			} catch (IOException e) {
				e.printStackTrace();
			}
			FullJobState fullJobState = (FullJobState) result.getDatas().get(0);
			if(fullJobState.getStatus().equals("DONE")||fullJobState.getStatus().equals("EXIT")){
				String status = "";
				if(fullJobState.getStatus().equals("DONE")){
					status = "0";
				}else {
					status = "1";
				}
				new QueryThread(job.getString("taskHash"),job.getString("jobId"),job.getString("algorithmHash"),status).start();
			}
		}
		return isSuccess;
	}

	/**
	 * restart task
	 *
	 * @return
	 */
	public boolean restartTask() {
        //2018-7-22修改，将下面注释掉，添加上面的内容
        //首先，将暂停的job重新开启,因为此时取新建上一次暂停的job对应的AlgorithmThread不现实，所以就在这里重启job
        boolean result = true;
        this.runningTaskBean.isPause = false;
        List<String> allJobIds = new ArrayList<>();
        //如果还有暂停中的作业，先将其完成
        if(this.runningTaskBean.getRunningJobs().size()>0)
        {
            for(Map.Entry<String,List<String>> one:this.runningTaskBean.getRunningJobs().entrySet())
            {
                allJobIds.addAll(one.getValue());
                AlgorithmThread algorithmThread = this.runningTaskBean.runningAlgorithms.get(one.getKey());
                //2019.1.8从数据库恢复的算法线程，其isPause不一定为true，这里置为true
                algorithmThread.isPause = true;
                algorithmThread.start();

            }
        }
        //没有的话，就直接开启下一个算法
        else{
            for(Map.Entry<String, Integer> map:this.runningTaskBean.restartHashes.entrySet()){
                if(map.getKey().contains("uiEnd")){
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    this.runningTaskBean.newestState = null;
                    this.runningTaskBean.setNewestAlgorithm(null);
                    this.runningTaskBean.historyDao.updateHistoryTaskState(this.runningTaskBean.state.toString()
                            , this.runningTaskBean.getTaskHash(),null,"running");
                }else if(!this.runningTaskBean.runningAlgorithms.containsKey(map.getKey())){
                    this.startHash(map.getKey(), map.getValue(),false);
                }
            }
        }
		this.updateState("任务名称：" + this.runningTaskBean.getTaskName() + "，恢复运行！" );
        return result;
	}

	/**
	 * stop task
	 *
	 * @return
	 */
	public boolean stopTask() {
//		this.runningTaskBean.isStop = true;
//		String newestAlgorithm = this.runningTaskBean.newestAlgorithm;
//		if(this.runningTaskBean.runningAlgorithms.containsKey(newestAlgorithm)){
//			AlgorithmThread algorithmThread = this.runningTaskBean.runningAlgorithms.get(newestAlgorithm);
//			return algorithmThread.stopAlgorithm();
//		}else{
//			return true;
//		}
		//2018-7-21修改
		boolean result = true;
		this.runningTaskBean.isStop = true;
		//将本子任务对应的正在运行的对象全部停下来
		for(Map.Entry<String,AlgorithmThread> one:this.runningTaskBean.runningAlgorithms.entrySet())
		{
			result = result&&one.getValue().stopAlgorithm();
		}
		//到数据库更新任务的状态
		result = result&&this.terminateTask("stopped");
		//result为true：一个或多个或所有算法都正确停止了或者完成了
		//result为false：一个或多个或所有算法停止失败了
		return result;
	}
	/**
	 * start one task
	 *
	 * @param
	 * @return
	 */
	public void startHash(String hash,Integer isAlgorithm, boolean isFirst) {
		/**
		 * not nested, just algorithm
		 */
		Log4jInit.logger.info("startHash isAlgorithm::"+isAlgorithm);
		if(isAlgorithm==1){
			beans.RunnableAlgorithm runnerableAlgorithm = (beans.RunnableAlgorithm)this.runningTaskBean.runnableObjects.get(hash);
			boolean start = true;
			/**
			 * the first has no previous object, can start right now
			 */
			if(isFirst){
				start = true;
			}else{
				/**
				 * start this object while the previous object completed
				 */
				for(Map.Entry<String, Integer> map:runnerableAlgorithm.preBlockMap.entrySet()){
					if(map.getKey().contains("uiData"))continue;
					start =  start && this.runningTaskBean.completedObjectHash.contains(map.getKey());
				}
			}

			if (start) {
				// hzj-0624 start
				AlgorithmThread algorithmThread = null;
				if(MyStringUtils.isNotEmpty(this.applyNode)){
					algorithmThread = new AlgorithmThread(this, runnerableAlgorithm,this.applyNode);
				}else{
					algorithmThread = new AlgorithmThread(this, runnerableAlgorithm);
				}
				//end
			
		//		AlgorithmThread algorithmThread = new AlgorithmThread(this, runnerableAlgorithm,this.runningTaskBean.getModelXmlDir());
				algorithmThread.start();
				this.updateState("算法组件名称：" + runnerableAlgorithm.getAlgorithmDetail().getName()+ "，开始运行！");

			}
		}
		/**
		 * nested
		 */
		else{
			RunnableTask runnableTask = (RunnableTask)this.runningTaskBean.runnableObjects.get(hash);
			TaskThread taskThread = new TaskThread(runnableTask);
			taskThread.start();
		}
	}

	/**
	 * 终止一个任务，statement取stopped或者finished
	 * @param statement
	 * @return
	 */
	public boolean terminateTask(String statement){
		this.runningTaskBean.setNewestAlgorithm(null);
		this.runningTaskBean.historyDao.updateHistoryTaskState(this.runningTaskBean.state.toString()
				, this.runningTaskBean.getTaskHash(),this.runningTaskBean.getBatchTaskHash(),statement);
		return true;
	}

	@Override
	public String toString() {
		return "TaskThread{" +
				"runningTaskBean=" + runningTaskBean +
				'}';
	}

	@Override
	public void run() {
		this.startTask();
	}
}